package snucse.teamd.math;

import java.lang.Math;
import java.util.ArrayList;
//Math.PI
public class Vec2 {
	private double x;
	private double y;
	private double z;
	
	public void print(){
		System.out.print("v=("+getX()+","+getY()+","+getZ()+")");
		System.out.println();
	}
	
	public double getZ() {
		return z;
	}
	public void setZ(double z) {
		this.z = z;
	}
	public Vec2(){
		setX(0);
		setY(0);
		z = 0; //z field is used for cross-product
		
	}
	public Vec2(double x_, double y_, double z_)
	{
		setX(x_);
		setY(y_);
		setZ(z_);
	}
	public Vec2(double x_, double y_){
		setX(x_);
		setY(y_);
		z = 0;
	}
	//object method
	public void set(double x_, double y_){
		setX(x_);
		setY(y_);
	}
	public Vec2(Vec2 v)
	{
		setX(v.getX());
		setY(v.getY());
		setZ(v.getZ());
	}
	
	public ArrayList<Double> getVecArr() {
		ArrayList<Double> vecArr = new ArrayList<Double>();
		vecArr.add(x);
		vecArr.add(y);
		return vecArr;
	}
	
	/**
	 * @return the x
	 */
	public double getX() {
		return x;
	}
	/**
	 * @return the y
	 */
	public double getY() {
		return y;
	}
	/**
	 * @param y the y to set
	 */
	public void setY(double y) {
		this.y = y;
	}
	/**
	 * @param x the x to set
	 */
	public void setX(double x) {
		this.x = x;
	}
	public Vec2 unaryMinus(){
		setX(-getX());
		setY(-getY());
		setZ(-getZ());
		return new Vec2(getX(),getY(),getZ());
	}
	
	public void scale(double s){
		setX(s*getX());
		setY(s*getY());
		setZ(s*getZ());
	}
	
	public double length()
	{
		return Math.sqrt(getX()*getX() + getY()*getY() + getZ()*getZ());
		
	}
	public void normalize()
	{
		double norm = this.length();
		if(norm > 0.0)
		{
			this.setX(this.getX()/norm);
			this.setY(this.getY()/norm);
			this.setZ(this.getZ()/norm);
		}
		else
		{
			this.setX(0.0);
			this.setY(0.0);
			this.setZ(0.0);
		}
	}

	public Vec2 perp()
	{
		return new Vec2(this.getY(), - this.getX(), this.getZ());
	}
	
	public Vec2 project(Edge e){
		Vec2 pt1=e.getV1(), pt2=e.getV2();
		
		double pX, pY;
		double a1,b1, a2,b2, c1, c2;
		
		a1=pt1.getX();
		b1=pt2.getX();
		a2=pt1.getY();
		b2=pt2.getY();
		c1=getX();
		c2=getY();
		
		if (pt1.getX()==pt2.getX()){
			pX=pt1.getX();
			pY=getY();
		}
		else if (pt1.getY()==pt2.getY()){
			pY=pt1.getY();
			pX=getX();
		}
		else{
			pX=(Math.pow(a1-b1, 2)*c1+Math.pow(a2-b2, 2)*(b1-b2)+(b2-a2)*(b1-a1)*c2) 
					/ (Math.pow(a2-b2, 2)+Math.pow(b1-a1, 2));
			pY=-((a1-b1)/(a2-b2)) * pX + 
					c2 +
					((a1-b1)/(a2-b2)) * c1;
		}
		return new Vec2(pX, pY);
	}
	
	public Vec2 getUnit()
	{
		double norm = this.length();
		if(norm > 0.0f)
		{return new Vec2(this.getX()/norm, this.getY()/norm, this.getZ()/norm);}
		else
		{return new Vec2(0.0f,0.0f,0.0f);}
	}
	
	//Vec2 class calculation
	public static double dot(Vec2 a, Vec2 b){
		return (a.getX() * b.getX() + a.getY() * b.getY() + a.getZ() * b.getZ());
	}
	
	//TODO implement!
	public static Vec2 plus(Vec2 a, Vec2 b){
		return new Vec2(a.getX()+b.getX(), a.getY()+b.getY(), a.getZ() + b.getZ());
	}
	
	public static Vec2 minus(Vec2 a, Vec2 b){
		return new Vec2(a.getX()-b.getX(), a.getY()-b.getY(), a.getZ() - b.getZ());
	}
	
	public static double distance(Vec2 a, Vec2 b){
		return minus(a,b).length();
	}
	public static Vec2 scalar(Vec2 v, double k)
	{
		return new Vec2(k*(v.getX()), k*(v.getY()), k*(v.getZ()));
	}
	public static double cross(Vec2 v1, Vec2 v2) //right-handed coordinate system
	{
		return v1.getX()*v2.getY() - v1.getY()*v2.getX();
	}
	public static double triangleArea(Vec2 v1, Vec2 v2)
	{
		return Math.abs(Vec2.cross(v1, v2))/2f;
	}
	public static Vec2 crossVec(Vec2 v1, Vec2 v2)
	{
		Vec2 v= new Vec2(
				v1.getY()*v2.getZ()-v1.getZ()*v2.getY(),
				v1.getZ()*v2.getX()-v1.getX()*v2.getZ(),
				v1.getX()*v2.getY()-v1.getY()*v2.getX()
				);
		
		return new Vec2(v.getX(), v.getY(),v.getZ());
	}
	
	public String toString() {
		return "[" + x + "," + y + "]";
	}
	
}
